#!/usr/bin/env python
# -*- coding:utf-8 -*-

"""
@file: commonService.py
@time: 2023/3/8 18:26

"""
import datetime
import mimetypes
import os

from flask import current_app, jsonify, Response
from werkzeug.datastructures import FileStorage

from utils.generate_id import GenerateID
from utils.loggings import loggings
from utils.response_code import RET, error_map_EN


class CommonService:
    @classmethod
    def save_upload_file(cls, **kwargs):
        """
            保存文件到本地服务器
        file: form中读取的文件
        file_type: 文件类型
        :return:
        """
        # 基于参数设置保存路径
        storage_type = kwargs.pop('storage_type')
        if storage_type == '0':
            return cls.save_upload_file_to_filesystem(**kwargs)
        elif storage_type == '1':
            return cls.save_upload_file_to_oss(**kwargs)
        else:
            # 保存到本地
            if current_app.config['FILE_STORAGE'] == 'local':
                return cls.save_upload_file_to_filesystem(**kwargs)
            elif current_app.config['FILE_STORAGE'] == 'oss':
                return cls.save_upload_file_to_oss(**kwargs)

    @classmethod
    def save_upload_pic(cls, **kwargs):
        # 基于参数设置保存路径
        storage_type = kwargs.pop('storage_type')
        if storage_type == '0':
            return cls.save_upload_pic_to_filesystem(**kwargs)
        elif storage_type == '1':
            return cls.save_upload_pic_to_oss(**kwargs)
        else:
            if current_app.config['PIC_STORAGE'] == 'local':
                return cls.save_upload_pic_to_filesystem(**kwargs)
            elif current_app.config['PIC_STORAGE'] == 'oss':
                return cls.save_upload_pic_to_oss(pic=kwargs.get('pic'))

    @classmethod
    def download_file(cls, **kwargs):
        """
            下载本地存储的文件
        file_name: 文件名
        file_url: 文件url
        file_type: 文件类型
        :return:
        """
        if current_app.config['FILE_STORAGE'] == 'local':
            return cls.download_local_file(**kwargs)
        elif current_app.config['FILE_STORAGE'] == 'oss':
            return cls.download_oss_file(**kwargs)

    @classmethod
    def save_upload_pic_to_filesystem(cls, pic, prefix_dir):
        """
            保存图片到本地
        :param prefix_dir: 父级文件目录
        :param pic: form中读取的文件
        :return: 文件路径，是否为文件夹（boolean）
        """
        from utils.generate_id import GenerateID

        current_time = datetime.datetime.now()
        parent_path = f'{prefix_dir}/{current_time.year}/{current_time.month}/{GenerateID.create_random_id()}'
        for p in pic:
            try:
                face_pic_stream = p.stream.read()
                suffix = p.filename.split('.')[-1]
                db_save_path = f'{parent_path}/{pic.filename.split(".")[-2]}.{suffix}'

                base_dir = os.path.dirname((os.path.dirname(os.path.abspath(__file__))))
                os.makedirs(
                    os.path.join(os.path.join(base_dir, current_app.config['PARENT_FILE_NAME']), parent_path),
                    exist_ok=True)
                local_save_path = os.path.join(os.path.join(base_dir, current_app.config['PARENT_FILE_NAME']),
                                               db_save_path).replace('\\', '/')
                with open(local_save_path, 'wb') as f:
                    f.write(face_pic_stream)
            except Exception as e:
                loggings.exception(1, e)
                return None
            return f"{current_app.config['PARENT_FILE_NAME']}/{parent_path}"


    @classmethod
    def save_upload_file_to_filesystem(cls, file, prefix_dir):
        """
            保存文件到本地服务器
        :param file: form中读取的文件
        :return:
        """
        from utils.generate_id import GenerateID

        current_time = datetime.datetime.now()
        parent_path = f'{prefix_dir}/{current_time.year}/{current_time.month}/{GenerateID.create_random_id()}'
        base_dir = os.path.dirname(os.path.dirname((os.path.dirname(os.path.abspath(__file__)))))
        try:
            for f in file:
                suffix = f.filename.split('.')[-1]
                db_save_path = f'{parent_path}/{f.filename.split(".")[-2]}.{suffix}'

                os.makedirs(os.path.join(os.path.join(base_dir, current_app.config['PARENT_FILE_NAME']), parent_path),
                            exist_ok=True)

                face_pic_stream = f.stream.read()

                local_save_path = os.path.join(os.path.join(base_dir, current_app.config['PARENT_FILE_NAME']),
                                               db_save_path).replace('\\', '/')
                with open(local_save_path, 'wb') as fil:
                    fil.write(face_pic_stream)

            return f"{current_app.config['PARENT_FILE_NAME']}/{parent_path}"
        except Exception as e:
            loggings.exception(1, e)
            return None

    @classmethod
    def download_local_file(cls, file_name, file_url):
        """
            下载本地存储的文件
        :param file_name: 文件名
        :param file_url: 文件url
        :return:
        """

        path = 'files'
        try:
            db_save_path = f'{path}/{file_url}'

            base_dir = os.path.dirname((os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
            local_save_path = os.path.join(os.path.join(base_dir, current_app.config['PARENT_FILE_NAME']),
                                           db_save_path).replace('\\', '/')
            with open(local_save_path, 'rb') as f:
                file_stream = f.read()

            response = Response(file_stream)
            mime_type = mimetypes.guess_type(file_url)[0]
            response.headers['Content-Type'] = mime_type
            response.headers['Content-Disposition'] = 'attachment; filename={}'.format(
                file_name.encode('UTF-8').decode('latin1'))
            return response
        except Exception as e:
            loggings.exception(1, e)
            jsonify(code=RET.IOERR, message='文件读取错误', data={'error': '文件读取错误'})


    @classmethod
    def save_upload_pd_to_filesystem(cls, data: pd.DataFrame, project_dir: str, path: str):
        suffix = path.split('.')[-1]
        if os.path.dirname(path).endswith('conversion'):
            path = os.path.dirname(os.path.dirname(path))
        else:
            path = os.path.dirname(path)
        save_path_dir = os.path.join(path, f"conversion")
        os.makedirs(os.path.join(project_dir, save_path_dir), exist_ok=True)
        save_path = f"{save_path_dir}/{GenerateID.create_random_id()}.{suffix}"
        if suffix == "csv":
            data.to_csv(os.path.join(project_dir, save_path), index=False)
        elif suffix == "xlsx" or suffix == "xls":
            data.to_excel(os.path.join(project_dir, save_path), index=False)
        return save_path.replace('\\', '/')

    @classmethod
    def get_upload_pd(cls, project_path: str, data_path: str, **kwargs):
        # 基于参数设置保存路径
        if kwargs.get('storage_type'):
            storage_type = kwargs.pop('storage_type')
            if storage_type == '0':
                return cls.get_upload_pd_from_file(project_path, data_path)
            elif storage_type == '1':
                return cls.get_upload_oss_pd(project_path, data_path)
        else:
            if data_path.startswith(current_app.config['PARENT_FILE_NAME']):
                return cls.get_upload_pd_from_file(project_path, data_path)
            else:
                if current_app.config['FILE_STORAGE'] == 'local':
                    return cls.get_upload_pd_from_file(project_path, data_path)
                elif current_app.config['FILE_STORAGE'] == 'oss':
                    return cls.get_upload_oss_pd(project_path, data_path)


    @classmethod
    def get_upload_plot(cls, project_path: str, data_path: str, **kwargs):
        """
            获取图片
        :param project_path: 项目路径
        :param data_path: 数据路径
        :param kwargs:
        :return:
        """
        # 基于参数设置保存路径
        if kwargs.get('storage_type'):
            storage_type = kwargs.pop('storage_type')
            if storage_type == '0':
                return cls.get_upload_pd_from_file(project_path, data_path)
            elif storage_type == '1':
                return cls.get_upload_oss_pd(project_path, data_path)
        else:
            if data_path.startswith(current_app.config['PARENT_FILE_NAME']):
                return cls.get_upload_plot_from_file(project_path, data_path)
            else:
                if current_app.config['FILE_STORAGE'] == 'local':
                    return cls.get_upload_plot_from_file(project_path, data_path)
                elif current_app.config['FILE_STORAGE'] == 'oss':
                    return cls.get_upload_plot_from_oss(project_path, data_path)

    @classmethod
    def get_upload_plot_from_file(cls, project_path: str, data_path: str):
        """
            获取本地存储的图片
        :param data_path: 文件地址

        :return:
        """
        path = os.path.join(project_path, data_path)
        with open(path, 'rb') as f:
            data = f.read()
            return data

    @classmethod
    def get_upload_file_list(cls, project_path: str, data_path: str, **kwargs):
        """
            获取文件列表
        :param project_path: 项目路径
        :param data_path: 数据路径
        :param kwargs:
        :return:
        """
        # 基于参数设置保存路径
        if kwargs.get('storage_type') is not None:
            storage_type = kwargs.pop('storage_type')
            if storage_type == '0':
                return cls.get_upload_file_list_from_file(project_path, data_path)
            elif storage_type == '1':
                return cls.get_upload_file_list_from_oss(project_path, data_path)
        else:
            if data_path.startswith(current_app.config['PARENT_FILE_NAME']):
                return cls.get_upload_file_list_from_file(project_path, data_path)
            else:
                if current_app.config['FILE_STORAGE'] == 'local':
                    return cls.get_upload_file_list_from_file(project_path, data_path)
                elif current_app.config['FILE_STORAGE'] == 'oss':
                    return cls.get_upload_file_list_from_oss(project_path, data_path)
    @classmethod
    def get_upload_file_list_from_file(cls, project_path: str, data_path: str):
        """
            获取阿里云oss对象存储的图片
        :param data_path: 文件url
        :return:
        """
        path = os.path.join(project_path, data_path)
        file_list = os.listdir(path.replace('\\', '/'))
        return file_list